package no.ntnu.idi.deid.patternmatching.search;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import org.apache.lucene.index.Term;
import org.apache.lucene.search.TermQuery;

import no.ntnu.idi.deid.config.Constants;
import no.ntnu.idi.deid.config.DataBases;
import no.ntnu.idi.deid.config.FilePaths;
import no.ntnu.idi.deid.documentunits.Phrase;
import no.ntnu.idi.deid.documentunits.Sentence;
import no.ntnu.idi.deid.patternmatching.search.dictionary.lucene.IndexBuilder;
import no.ntnu.idi.deid.patternmatching.search.dictionary.lucene.SearchField;
import no.ntnu.idi.deid.patternmatching.search.dictionary.medicalcodes.ICD10_Codes;
import no.ntnu.idi.deid.patternmatching.search.dictionary.medicalcodes.ICPC2_Codes;
import no.ntnu.idi.deid.patternmatching.search.dictionary.medicalcodes.NCMP_Codes;
import no.ntnu.idi.deid.patternmatching.search.dictionary.medicalcodes.NCRP_codes;
import no.ntnu.idi.deid.patternmatching.search.dictionary.medicalcodes.NCSP_Codes;
import no.ntnu.idi.deid.patternmatching.search.dictionary.medicalcodes.Snomed_Elements;
import no.ntnu.idi.deid.patternmatching.search.dictionary.phrase.Simstring;
import no.ntnu.idi.deid.preprocessor.sentenizer.Ngram;
import no.ntnu.idi.deid.searchresultunits.CategoryTag;
import no.ntnu.idi.deid.searchresultunits.Tag;

public class SentenceSearch {
	
	private static boolean hasGeneratedDatabases = false;
	private static List<File> databaseFiles = new ArrayList<File>();
	private Sentence mSentence;
	
	public SentenceSearch(Sentence sentence) {
		mSentence = sentence;
		buildSimstringDataBases();
	}
	
	public void nGramSearch(int n) {
		Ngram ngram = new Ngram(mSentence,n);
		for(int i = 0; i<ngram.size(); i++) {
			SearchField searchfield;
			Set<CategoryTag> resultSet = Collections.emptySet();
			String word = ngram.getNGramStrippedString(i);
			TermQuery termQuery = new TermQuery(new Term(IndexBuilder.FIELD_CONTENTS, word));
			try {
				searchfield = SearchField.generateStandardSearchField(FilePaths.getTermIndexDirectory());
				resultSet = searchfield.searchAndReturnSet(termQuery);
				searchfield.closeReader();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if(!resultSet.isEmpty()) {
				for(CategoryTag tag: resultSet) {
					mSentence.addPhrase(new Phrase(ngram.getList(i),tag));
				}
			}
		}
	}
	
	public void runSimstring() {
		for (File file : databaseFiles) {
			List<String> resultList = Simstring
					.simStringQuery(file, new File(
							Constants.TEMP_PHRASERESULT_FILENAME),
							Constants.COSINE_SIMILIRITY_THRESHOLD,
							mSentence.getStripped());
			if (!resultList.isEmpty()) {	
				for (String phraseString : resultList) {
					Phrase resultPhrase = mSentence.findPhrase(Constants.distanceMeasure, phraseString, Constants.MAXIMUM_DISTANCE_MEASURE);
					if (resultPhrase != null) {
						resultPhrase
								.setCategoryTag(handleMatch(
										file, phraseString));
							mSentence.addPhrase(resultPhrase);
					}
			}
		}	
		
	}
}

	private static void buildSimstringDataBases() {
		if(!hasGeneratedDatabases) {
			for(DataBases database: DataBases.values()) {
				databaseFiles.add(Simstring.buildSimstringDatabase(database.getTextFile(), database.getDataBaseFile()));
			}			
		}
		hasGeneratedDatabases = true;
	}
		
	private CategoryTag handleMatch(File file, String phrase) {
		if(file.getPath().equals(Constants.NCSP_DB_FILE.getPath())) {
			return NCSP_Codes.searchExactDescription(phrase);
		}
		else if(file.getPath().equals(Constants.ICPC_DB_FILE.getPath())) {
			return ICPC2_Codes.searchExactICPC2Description(phrase);
		}
		else if(file.getPath().equals(Constants.ICD10_DB_FILE.getPath())) {
			return ICD10_Codes.searchExactICD10Description(phrase);
		}
		else if(file.getPath().equals(Constants.SNOMED_DB_FILE.getPath())) {
			return Snomed_Elements.searchDescriptionWithoutUNS(phrase);
		}
		else if(file.getPath().equals(Constants.NCMP_DB_FILE.getPath())) {
			return NCMP_Codes.searchExactNCMPDescription(phrase);
		}
		else if(file.getPath().equals(Constants.NCRP_DB_FILE)) {
			return NCRP_codes.searchExactDescription(phrase);
		}
		else if(file.getPath().equals(Constants.ORGNAME_DB_FILE.getPath())) {
			return new CategoryTag(Tag.ORGANIZATIONNAME);
		}
		else {
			return null;
		}
	}
}
